from telnetlib import NOP

from insts.compare.compare import LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IF_EQ, IF_NE, IF_LT, IF_GE, IF_GT, IF_LE, \
    IF_ICMP_EQ, IF_ICMP_NE, IF_ICMP_LT, IF_ICMP_GE, IF_ICMP_GT, IF_ICMP_LE, IF_ACMP_EQ, IF_ACMP_NE
from insts.control.go_to import GOTO
from insts.control.lookup_switch import TABLE_SWITCH, LOOKUP_SWITCH
from insts.control.return_inst import IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN
from insts.conts.constant import ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, \
    LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, BIPUSH, SIPUSH, LDC, LDC_W2
from insts.convert.x2y import I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S
from insts.inst import Instruction
from insts.load.load import ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, LLOAD_0, LLOAD_1, \
    LLOAD_3, LLOAD_2, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, ALOAD_0, ALOAD_1, ALOAD_2, \
    ALOAD_3
from insts.load.xaload import IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD
from insts.math.incr import INCR
from insts.math.opeImp import IADD, LADD, ISUB, FADD, DADD, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, \
    DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, \
    IXOR, LXOR
from insts.refrence.field_inst import GET_STATIC_FIELD, PUT_STATIC_FIELD, GET_FIELD, PUT_FIELD
from insts.stack.stack import POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
from insts.store.store import ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, LSTORE_0, \
    LSTORE_1, LSTORE_2, LSTORE_3, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, \
    ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3
from insts.store.xstore import IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE


class Instructions:

    @staticmethod
    def newInstruction(opcode) -> Instruction:
        if opcode == 0x00:
            return NOP
        elif opcode == 0x01:
            return ACONST_NULL(opcode)
        elif opcode == 0x02:
            return ICONST_M1(opcode)
        elif opcode == 0x03:
            return ICONST_0(opcode)
        elif opcode == 0x04:
            return ICONST_1(opcode)
        elif opcode == 0x05:
            return ICONST_2(opcode)
        elif opcode == 0x06:
            return ICONST_3(opcode)
        elif opcode == 0x07:
            return ICONST_4(opcode)
        elif opcode == 0x08:
            return ICONST_5(opcode)
        elif opcode == 0x09:
            return LCONST_0(opcode)
        elif opcode == 0x0A:
            return LCONST_1(opcode)
        elif opcode == 0x0B:
            return FCONST_0(opcode)
        elif opcode == 0x0C:
            return FCONST_1(opcode)
        elif opcode == 0x0D:
            return FCONST_2(opcode)
        elif opcode == 0x0E:
            return DCONST_0(opcode)
        elif opcode == 0x0F:
            return DCONST_1(opcode)
        elif opcode == 0x10:
            return BIPUSH(opcode)
        elif opcode == 0x11:
            return SIPUSH(opcode)
        elif opcode == 0x12:
            return LDC(opcode)
        elif opcode == 0x13:
            return LDC(opcode)  # LDC_W
        elif opcode == 0x14:
            return LDC_W2(opcode)  # LDC2_W
        elif opcode == 0x15:
            return ILOAD(opcode)
        elif opcode == 0x16:
            return LLOAD(opcode)
        elif opcode == 0x17:
            return FLOAD(opcode)
        elif opcode == 0x18:
            return DLOAD(opcode)
        elif opcode == 0x19:
            return ALOAD(opcode)
        elif opcode == 0x1A:
            return ILOAD_0(opcode)
        elif opcode == 0x1B:
            return ILOAD_1(opcode)
        elif opcode == 0x1C:
            return ILOAD_2(opcode)
        elif opcode == 0x1D:
            return ILOAD_3(opcode)
        elif opcode == 0x1E:
            return LLOAD_0(opcode)
        elif opcode == 0x1F:
            return LLOAD_1(opcode)
        elif opcode == 0x20:
            return LLOAD_2(opcode)
        elif opcode == 0x21:
            return LLOAD_3(opcode)
        elif opcode == 0x22:
            return FLOAD_0(opcode)
        elif opcode == 0x23:
            return FLOAD_1(opcode)
        elif opcode == 0x24:
            return FLOAD_2(opcode)
        elif opcode == 0x25:
            return FLOAD_3(opcode)
        elif opcode == 0x26:
            return DLOAD_0(opcode)
        elif opcode == 0x27:
            return DLOAD_1(opcode)
        elif opcode == 0x28:
            return DLOAD_2(opcode)
        elif opcode == 0x29:
            return DLOAD_3(opcode)
        elif opcode == 0x2A:
            return ALOAD_0(opcode)
        elif opcode == 0x2B:
            return ALOAD_1(opcode)
        elif opcode == 0x2C:
            return ALOAD_2(opcode)
        elif opcode == 0x2D:
            return ALOAD_3(opcode)
        elif opcode == 0x2E:
            return IALOAD(opcode)
        elif opcode == 0x2F:
            return LALOAD(opcode)
        elif opcode == 0x30:
            return FALOAD(opcode)
        elif opcode == 0x31:
            return DALOAD(opcode)
        elif opcode == 0x32:
            return AALOAD(opcode)
        elif opcode == 0x33:
            return BALOAD(opcode)
        elif opcode == 0x34:
            return CALOAD(opcode)
        elif opcode == 0x35:
            return SALOAD(opcode)
        elif opcode == 0x36:
            return ISTORE(opcode)
        elif opcode == 0x37:
            return LSTORE(opcode)
        elif opcode == 0x38:
            return FSTORE(opcode)
        elif opcode == 0x39:
            return DSTORE(opcode)
        elif opcode == 0x3A:
            return ASTORE(opcode)
        elif opcode == 0x3B:
            return ISTORE_0(opcode)
        elif opcode == 0x3C:
            return ISTORE_1(opcode)
        elif opcode == 0x3D:
            return ISTORE_2(opcode)
        elif opcode == 0x3E:
            return ISTORE_3(opcode)
        elif opcode == 0x3F:
            return LSTORE_0(opcode)
        elif opcode == 0x40:
            return LSTORE_1(opcode)
        elif opcode == 0x41:
            return LSTORE_2(opcode)
        elif opcode == 0x42:
            return LSTORE_3(opcode)
        elif opcode == 0x43:
            return FSTORE_0(opcode)
        elif opcode == 0x44:
            return FSTORE_1(opcode)
        elif opcode == 0x45:
            return FSTORE_2(opcode)
        elif opcode == 0x46:
            return FSTORE_3(opcode)
        elif opcode == 0x47:
            return DSTORE_0(opcode)
        elif opcode == 0x48:
            return DSTORE_1(opcode)
        elif opcode == 0x49:
            return DSTORE_2(opcode)
        elif opcode == 0x4A:
            return DSTORE_3(opcode)
        elif opcode == 0x4B:
            return ASTORE_0(opcode)
        elif opcode == 0x4C:
            return ASTORE_1(opcode)
        elif opcode == 0x4D:
            return ASTORE_2(opcode)
        elif opcode == 0x4E:
            return ASTORE_3(opcode)
        elif opcode == 0x4F:
            return IASTORE(opcode)
        elif opcode == 0x50:
            return LASTORE(opcode)
        elif opcode == 0x51:
            return FASTORE(opcode)
        elif opcode == 0x52:
            return DASTORE(opcode)
        elif opcode == 0x53:
            return AASTORE(opcode)
        elif opcode == 0x54:
            return BASTORE(opcode)
        elif opcode == 0x55:
            return CASTORE(opcode)
        elif opcode == 0x56:
            return SASTORE(opcode)
        elif opcode == 0x57:
            return POP(opcode)
        elif opcode == 0x58:
            return POP2(opcode)
        elif opcode == 0x59:
            return DUP(opcode)
        elif opcode == 0x5A:
            return DUP_X1(opcode)
        elif opcode == 0x5B:
            return DUP_X2(opcode)
        elif opcode == 0x5C:
            return DUP2(opcode)
        elif opcode == 0x5D:
            return DUP2_X1(opcode)
        elif opcode == 0x5E:
            return DUP2_X2(opcode)
        elif opcode == 0x5F:
            return SWAP(opcode)
        elif opcode == 0x60:
            return IADD(opcode)
        elif opcode == 0x61:
            return LADD(opcode)
        elif opcode == 0x62:
            return FADD(opcode)
        elif opcode == 0x63:

            return DADD(opcode)
        elif opcode == 0x64:
            return ISUB(opcode)  # 减法
        elif opcode == 0x65:
            return LSUB(opcode)  # 减法
        elif opcode == 0x66:
            return FSUB(opcode)  # 减法
        elif opcode == 0x67:
            return DSUB(opcode)  # 减法
        elif opcode == 0x68:
            return IMUL(opcode)  # 乘法
        elif opcode == 0x69:
            return LMUL(opcode)

        elif opcode == 0x6A:
            return FMUL(opcode)  # 乘法
        elif opcode == 0x6B:
            return DMUL(opcode)  # 乘法

        elif opcode == 0x6C:
            return IDIV(opcode)  # 除法
        elif opcode == 0x6D:
            return LDIV(opcode)  # 除法
        elif opcode == 0x6E:
            return FDIV(opcode)  # 除法
        elif opcode == 0x6F:
            return DDIV(opcode)  # 除法

        elif opcode == 0x70:
            return IREM(opcode)  # 取余
        elif opcode == 0x71:
            return LREM(opcode)  # 取余
        elif opcode == 0x72:
            return FREM(opcode)  # 取余
        elif opcode == 0x73:
            return DREM(opcode)  # 取余

        elif opcode == 0x74:
            return INEG(opcode)  # 取负
        elif opcode == 0x75:
            return LNEG(opcode)  # 取负
        elif opcode == 0x76:
            return FNEG(opcode)  # 取负
        elif opcode == 0x77:
            return DNEG(opcode)  # 取负

        elif opcode == 0x78:
            return ISHL(opcode)  # 左移
        elif opcode == 0x79:
            return LSHL(opcode)  # 左移
        elif opcode == 0x7A:
            return ISHR(opcode)  # 右移
        elif opcode == 0x7B:
            return LSHR(opcode)  # 右移
        elif opcode == 0x7C:
            return IUSHR(opcode)  # 无符号右移
        elif opcode == 0x7D:
            return LUSHR(opcode)  # 无符号右移
        elif opcode == 0x7E:
            return IAND(opcode)  # 按位与
        elif opcode == 0x7F:
            return LAND(opcode)  # 按位与
        elif opcode == 0x80:
            return IOR(opcode)  # 按位或
        elif opcode == 0x81:
            return LOR(opcode)  # 按位或
        elif opcode == 0x82:
            return IXOR(opcode)  # 按位异或
        elif opcode == 0x83:
            return LXOR(opcode)  # 按位异或
        elif opcode == 0x84:
            return INCR(opcode)  # 增量
        elif opcode == 0x85:
            return I2L(opcode)  # 转换为long
        elif opcode == 0x86:
            return I2F(opcode)  # 转换为float
        elif opcode == 0x87:
            return I2D(opcode)  # 转换为double
        elif opcode == 0x88:
            return L2I(opcode)  # 转换为int
        elif opcode == 0x89:
            return L2F(opcode)  # 转换为float
        elif opcode == 0x8A:
            return L2D(opcode)  # 转换为double
        elif opcode == 0x8B:
            return F2I(opcode)  # 转换为int
        elif opcode == 0x8C:
            return F2L(opcode)  # 转换为long
        elif opcode == 0x8D:
            return F2D(opcode)  # 转换为double
        elif opcode == 0x8E:
            return D2I(opcode)  # 转换为int
        elif opcode == 0x8F:
            return D2L(opcode)  # 转换为long
        elif opcode == 0x90:
            return D2F(opcode)  # 转换为float
        elif opcode == 0x91:
            return I2B(opcode)  # 转换为byte
        elif opcode == 0x92:
            return I2C(opcode)  # 转换为char
        elif opcode == 0x93:
            return I2S(opcode)  # 转换为short
        elif opcode == 0x94:
            return LCMP(opcode)  # 比较long
        elif opcode == 0x95:
            return FCMPL(opcode)  # 比较float
        elif opcode == 0x96:
            return FCMPG(opcode)  # 比较float
        elif opcode == 0x97:
            return DCMPL(opcode)  # 比较double
        elif opcode == 0x98:
            return DCMPG(opcode)  # 比较double
        elif opcode == 0x99:
            return IF_EQ(opcode)  # if相等
        elif opcode == 0x9A:
            return IF_NE(opcode)  # if不相等
        elif opcode == 0x9B:
            return IF_LT(opcode)  # if小于
        elif opcode == 0x9C:
            return IF_GE(opcode)  # if大于等于
        elif opcode == 0x9D:
            return IF_GT(opcode)  # if大于
        elif opcode == 0x9E:
            return IF_LE(opcode)  # if小于等于
        elif opcode == 0x9F:
            return IF_ICMP_EQ(opcode)  # if int相等
        elif opcode == 0xA0:
            return IF_ICMP_NE(opcode)  # if int不相等
        elif opcode == 0xA1:
            return IF_ICMP_LT(opcode)  # if int小于
        elif opcode == 0xA2:
            return IF_ICMP_GE(opcode)  # if int大于等于
        elif opcode == 0xA3:
            return IF_ICMP_GT(opcode)  # if int大于
        elif opcode == 0xA4:
            return IF_ICMP_LE(opcode)  # if int小于等于
        elif opcode == 0xA5:
            return IF_ACMP_EQ(opcode)  # if ref相等
        elif opcode == 0xA6:
            return IF_ACMP_NE(opcode)  # if ref不相等
        elif opcode == 0xA7:
            return GOTO(opcode)  # 无条件跳转
        elif opcode == 0xA8:
            # return JSR(opcode)  # 跳转到子例程
            pass
        elif opcode == 0xA9:
            # return RET(opcode)  # 返回
            pass
        elif opcode == 0xAA:
            return TABLE_SWITCH(opcode)  # 表跳转
        elif opcode == 0xAB:
            return LOOKUP_SWITCH(opcode)  # 散列表跳转
        elif opcode == 0xAC:
            return IRETURN(opcode)  # 返回int
        elif opcode == 0xAD:
            return LRETURN(opcode)  # 返回long
        elif opcode == 0xAE:
            return FRETURN(opcode)  # 返回float
        elif opcode == 0xAF:
            return DRETURN(opcode)  # 返回double
        elif opcode == 0xB0:
            return ARETURN(opcode)  # 返回ref
        elif opcode == 0xB1:
            return RETURN(opcode)  # 无条件返回
        elif opcode == 0xB2:
            return GET_STATIC_FIELD(opcode)  # 获取静态字段
        elif opcode == 0xB3:
            return PUT_STATIC_FIELD(opcode)  # 设置静态字段
        elif opcode == 0xB4:
            return GET_FIELD(opcode)  # 获取字段
        elif opcode == 0xB5:
            return PUT_FIELD(opcode)  # 设置字段
        else:
            pass
